﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;

namespace SharpDB.Utils
{
    public static class Util
    {

        #region 简单数据类型 转换
        /// <summary>
        /// 对象类型转换
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public static T ChangeType<T>(object obj, string markName = "")
        {
            try
            {
                object result = null;
                Type toType = typeof(T);
                //Type fromType = null;
                if (obj == null || obj == DBNull.Value)
                {
                    if ((toType.IsGenericType && toType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))))
                    {
                        return default(T);
                    }
                    else if (toType.IsValueType)
                    {
                        throw new Exception("不能将null值转换为" + toType.Name + "类型!");
                    }
                    else
                    {
                        return default(T);
                    }
                }
                else
                {
                    //fromType = obj.GetType();

                    if ((toType.IsGenericType && toType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))))
                    {
                        toType = Nullable.GetUnderlyingType(toType) ?? toType;
                    }

                    if (toType.Name == "Object")
                    {
                        return (T)obj;
                    }

                    if (toType.IsEnum)
                    {
                        result = Enum.Parse(toType, obj.ToString(), true);
                    }
                    else if (toType.IsAssignableFrom(typeof(Guid)))
                    {
                        result = Guid.Parse(obj.ToString());
                    }
                    else
                    {
                        result = Convert.ChangeType(obj, toType);
                    }
                    return (T)result;
                }
            }
            catch (Exception ex)
            {
                throw new ArgumentException(ex.Message, markName, ex);
            }
        }

        /// <summary>
        /// 对象类型转换，转换失败，返回默认值
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="obj">对象</param>
        /// <param name="def">默认值</param>
        /// <returns></returns>
        public static T ChangeType<T>(object obj, T def)
        {
            try
            {
                if (obj == null)
                {
                    return def;
                }
                return ChangeType<T>(obj);
            }
            catch
            {
                return def;
            }
        }

        public static object ChangeType(object obj, Type conversionType)
        {
            Type type = conversionType;
            type = Nullable.GetUnderlyingType(type) ?? type;
            if (type != null)
            {
                object result = null;
                if (obj != null && obj != DBNull.Value)
                {
                    if (type.IsAssignableFrom(typeof(string)))
                    {
                        result = obj.ToString();
                    }
                    else if (type.IsEnum)
                    {
                        result = Enum.Parse(type, obj.ToString(), true);
                    }
                    else if (type.IsAssignableFrom(typeof(Guid)))
                    {
                        result = Guid.Parse(obj.ToString());
                    }
                    else
                    {
                        result = Convert.ChangeType(obj, type);
                    }
                }
                else
                {
                    if (type.IsAssignableFrom(typeof(string)) || type.IsAssignableFrom(typeof(object)))
                    {
                        result = null;
                    }
                    else
                    {
                        throw new Exception("不能将null值转换为" + type.Name + "类型!");
                    }
                }
                return result;
            }
            return Convert.ChangeType(obj, type);
        }

        public static object ChangeType(object obj, Type conversionType, object def)
        {
            try
            {
                if (obj == null)
                {
                    return def;
                }
                return ChangeType(obj, conversionType);
            }
            catch
            {
                return def;
            }
        }
        #endregion

        internal static DbType GetValueDbType(object objvalue, DbParameter para)
        {
            Type tyval = objvalue.GetType();
            Type typeVal = Nullable.GetUnderlyingType(tyval) ?? tyval;

            DbType dbType = DbType.AnsiString;
            DateTime dtime;
            Guid gid;
            if (typeVal.IsEnum && Enum.GetUnderlyingType(typeVal) == typeof(byte))
            {
                dbType = DbType.Int32;
            }
            else if (typeVal == typeof(byte[]))
            {
                dbType = DbType.Binary;
            }
            else if (DateTime.TryParse(objvalue.ToString(), out dtime)
               && !Regex.IsMatch(objvalue.ToString(), @"^\d{4}[.-/]{1}\d{1,2}$"))
            {
                dbType = DbType.DateTime;
            }
            else if (Guid.TryParse(objvalue.ToString(), out gid))
            {
                dbType = DbType.String;
                para.Value = objvalue.ToString();
            }
            else
            {

            }
            return dbType;
        }

        /// <summary>
        /// 拼接in sql语句
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="columnName">列名</param>
        /// <param name="values">元素值</param>
        /// <param name="isNotIn">not in 或 in </param>
        /// <returns></returns>
        public static string SqlIn<T>(string columnName, T[] values, bool isNotIn = false)
        {
            string result = string.Empty;
            if (values == null || values.Length <= 0)
            {
                return string.Empty;
            }
            List<string> lst = new List<string>();
            foreach (T obj in values)
            {
                if (obj != null)
                {
                    string val = obj.ToString();
                    if (val.StartsWith("'") && val.EndsWith("'"))
                    {
                        val = val.Replace("'", "'''");
                        lst.Add(val);
                        continue;
                    }
                    lst.Add("'" + val + "'");
                }
            }
            if (lst.Count > 0)
            {
                result = " and " + columnName + " " + (isNotIn ? "not" : "") + " in (" + string.Join(",", lst) + ") ";
            }
            return result;
        }

        /// <summary>
        /// 拼接多条 like 语句
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="columnName">列名</param>
        /// <param name="values">元素值</param>
        /// <param name="isOrLike">or like 或 and like</param>
        /// <returns></returns>
        public static string SqlLike<T>(string columnName, T[] values, bool isOrLike = true)
        {
            string result = string.Empty;
            if (values == null || values.Length <= 0)
            {
                return string.Empty;
            }
            List<string> lst = new List<string>();
            foreach (T obj in values)
            {
                if (obj != null)
                {
                    string like_sql = columnName + " like '%{0}%' ";
                    string temp_sql = string.Empty;
                    string val = obj.ToString();
                    if (val.StartsWith("'") && val.EndsWith("'"))
                    {
                        val = val.Replace("'", "''");
                        temp_sql = string.Format(like_sql, val);
                        lst.Add(temp_sql);
                        continue;
                    }
                    temp_sql = string.Format(like_sql, val);
                    lst.Add(temp_sql);
                }
            }
            if (lst.Count>0)
            {
                result = " and (" + (string.Join((isOrLike ? " or" : " and "), lst)) + ") ";
            }            
            return result;
        }


        /// <summary>
        /// 获取执行异常的Sql
        /// </summary>
        /// <param name="strSql"></param>
        /// <param name="cmdParms"></param>
        /// <returns></returns>
        public static dynamic GetEXSql(string strSql, params IDataParameter[] cmdParms)
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();
            dict.Add("StrSql", strSql);
            if (cmdParms != null && cmdParms.Length > 0)
            {
                Dictionary<string, object> dictPara = new Dictionary<string, object>();
                foreach (var para in cmdParms)
                {
                    dictPara.Add(para.ParameterName, para.Value);
                }
                dict.Add("cmdParms", dictPara);
            }
            return dict;
        }

    }
}
